<?php
/**
 * Created by PHPStorm
 * User: xiest
 * Date: 2021/4/6
 * Email: <939369942@qq.com>
 */
namespace basic\base;

use think\Container;
use think\helper\Str;

abstract class BaseManager
{
    /**
     * 驱动的命名空间
     * @var null
     */
    protected $nameSpace = null;

    /**
     * 额外配置
     * @var null
     */
    protected $configFile = null;

    /**
     * 配置
     * @var array
     */
    protected $config = [];

    /**
     * 驱动
     * @var array
     */
    protected $drivers = null;


    /**
     * 驱动名称
     * @var null
     */
    protected $name = null;

    /**
     * BaseManager constructor.
     * @param string|array|int  $name 驱动名称
     * @param array $config  配置
     */
    public function __construct($name = null,$config = [])
    {
        if(!$name) $name = $this->getDefaultDriver();
        $this->name = $name;
        $this->config = $config;
    }

    public function __call($name, $arguments)
    {
        return $this->driver()->{$name}(...$arguments);
    }


    protected function driver()
    {
        if($this->drivers) return $this->drivers;
        return $this->drivers = $this->CreateDriver();
    }


    protected function CreateDriver()
    {

        $class = $this->getClass($this->name);
        return $this->invokeClass($class);
    }

    /**
     * 获取驱动类
     * @param string $name
     * @return string
     * User: xiest
     * Date: 2021/4/6
     */
    public function getClass(string $name)
    {
        if($this->nameSpace || false !== strpos($name,'\\'))
        {
            $class = false !== strpos($name, '\\') ? $name : $this->nameSpace .'\\'. Str::studly($name);

            if(class_exists($class))
                return $class;
        }

        throw new \InvalidArgumentException("Driver [$name] not supported.");
    }

    /**
     * 实例化类
     * @param $class
     * @return mixed
     * @throws \ReflectionException
     * User: xiest
     * Date: 2021/4/6
     */
    public function invokeClass($class)
    {
        if (!class_exists($class)) {
            throw new \RuntimeException('class not exists: ' . $class);
        }

        $this->getConfigFile();
        $handle = Container::getInstance()->invokeClass($class, [$this->name, $this->config, $this->configFile]);
        $this->config = [];
        return $handle;
    }

    /**
     * 提取配置文件名
     * @return $this
     * @throws \ReflectionException
     * User: xiest
     * Date: 2021/4/6
     */
    protected function getConfigFile()
    {
        if (is_null($this->configFile)) {
            $this->configFile = strtolower((new \ReflectionClass($this))->getShortName());
        }
        return $this;
    }

    abstract protected function getDefaultDriver();
}